package com.dahua.beanfactorypostprocessor;

import com.dahua.aop.UserService;
import com.dahua.constructor.OrderService;
import com.dahua.luban.Resolve;
import com.dahua.luban.ResolveA;
import com.dahua.zidingyisaomiaoqimofangmybatisdisanjieke.CustomScanner;
import com.dahua.zidingyisaomiaoqimofangmybatisdisanjieke.MyComponent;
import com.dahua.zidingyisaomiaoqimofangmybatisdisanjieke.TestMyComponent;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * @author chen_MingLiang
 * @version 1.0
 * @date 2020/1/26 18:46
 */
//执行的时机:完成扫描,parse,并且在beanDefinitionMap.put之后
	@Component//这个类要加入到容器才生效
public class LubanBeanFactoruPostProcessor implements BeanFactoryPostProcessor, ApplicationContextAware {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		GenericBeanDefinition  beanService = (GenericBeanDefinition) beanFactory.getBeanDefinition("beanService");//用子类接受,多了一些扩展
		//修改bean的定义.这个时候,如果我们还去拿原来的beanService,就会报错,因为容器中已经不存在beanService,被修改成了Test
		beanService.setBeanClass(Test.class);
		String[] beanNamesForType = beanFactory.getBeanNamesForType(Resolve.class,true,false);
		Map<String, Resolve> beansOfType = beanFactory.getBeansOfType(Resolve.class);
		for (Map.Entry<String, Resolve> stringResolveEntry : beansOfType.entrySet()) {
			stringResolveEntry.getValue().resolve("getBeansOfType+");
		}
		for (String name : beanNamesForType) {
			Resolve bean = beanFactory.getBean(name, Resolve.class);
			if (bean instanceof ResolveA) {
				bean.resolve("type+");
			}
		}
		//添加一个Supplier.这样的话在推断构造方法的时候,如果我们是手动注入,并且有两个有参构造,并且没有提供无参构造,也不会报错.跟factoryMethod一样
		//beanService.setInstanceSupplier(()->new OrderService(beanFactory.getBean(UserService.class)));

	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		//自定义扫描器。
		CustomScanner customScanner = new CustomScanner((AnnotationConfigApplicationContext)applicationContext);
		customScanner.addIncludeFilter(new AnnotationTypeFilter(MyComponent.class));
		int count = customScanner.scan("com.dahua");
		//这里打印2 我自己添加了两个@MyComponent注解的类,被扫描了出来
		System.out.println("自己添加了两个@MyComponent注解的类"+count);
		TestMyComponent bean = applicationContext.getBean(TestMyComponent.class);
		System.out.println("自己添加了两个@MyComponent注解的类"+bean);
		//通过这个方法也可以找到对应类型的bean
		//BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);

	}
}
